﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace Samurai.Workflow
{
    public class ParallelWorkflow<T> : IParallelWorkflow<T> where T : class, IWorkflowContext 
    {
        private Dictionary<ISequentialWorkflow<T>, Thread> _workflows;

        /// <summary>
        /// Initializes a new instance of the <see cref="ParallelWorkflow&lt;T&gt;"/> class.
        /// </summary>
        public ParallelWorkflow()
        {
            _workflows = new Dictionary<ISequentialWorkflow<T>, Thread>();
        }

        /// <summary>
        /// Occurs when [workflow completed].
        /// </summary>
        public event EventHandler<WorkflowCompletedEventArgs<T>> WorkflowCompleted;

        /// <summary>
        /// Occurs when [workflow failed].
        /// </summary>
        public event EventHandler<WorkflowCompletedEventArgs<T>> WorkflowFailed;

        /// <summary>
        /// Starts the workflow by executing the all registered workflows
        /// </summary>
        public void Start()
        {
            foreach (var kvp in _workflows)
                kvp.Value.Start();
        }

        /// <summary>
        /// Stops the workflows executing and raises WorkflowCompleted event.
        /// </summary>
        public void Stop()
        {
            foreach (var kvp in _workflows)
            {
                if (kvp.Value.IsAlive)
                    kvp.Value.Abort();
            }
        }

        /// <summary>
        /// Gets the number of sequential workflows registered with this instance.
        /// </summary>
        /// <value>The count.</value>
        public int Count
        {
            get
            {
                return _workflows.Count;
            }
        }

        /// <summary>
        /// Registers a workflow to be executed in parallel with all other registered workflows.
        /// </summary>
        /// <param name="sequentialWorkflow">The sequential workflow.</param>
        public void RegisterWorkflow(ISequentialWorkflow<T> sequentialWorkflow)
        {
            if (sequentialWorkflow == null) throw new ArgumentNullException("sequentialWorkflow");
            if (_workflows == null) _workflows = new Dictionary<ISequentialWorkflow<T>, Thread>();

            _workflows.Add(sequentialWorkflow, new Thread(sequentialWorkflow.Start));
        }

        /// <summary>
        /// Clears all registered sequential workflows from this instance.
        /// </summary>
        public void Clear()
        {
            _workflows.Clear();
        }
    }
}
